package com.lagou.edu.filter;

import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * Created by shixi  on 2021/1/28
 */
@Slf4j
@Component
@Order(-1) //数值越⼩，优先级越⾼
public class TokenFilter implements GlobalFilter {
    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("    TokenFilter ... ");
        //验证token
        ServerHttpRequest request = exchange.getRequest();

        String value = request.getPath().value();
        if(value.startsWith("/user/register") || value.startsWith("/user/isRegistered")){
            return chain.filter(exchange);
        }
        if(value.startsWith("/user/login")){
            //登录成功后，将token放入cookie中
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {
                        ServerHttpResponse response = exchange.getResponse();
                        HttpHeaders headers = response.getHeaders();
                        log.info(JSONObject.toJSONString(headers));
                        List<String> list = headers.get("Set-Cookie");
                        if(list!=null) {
                            String[] split = list.get(0).split(";")[0].split("=");
                            String token = split[1];
                            ResponseCookie.ResponseCookieBuilder token1 =
                                    ResponseCookie.from("token", token);
                            // 可以为负数，表示此cookie只是存储在浏览器内存里，只要关闭浏览器，此cookie就会消失
                            // maxAge默认值为-1。
                            // 还可以为0，表示从客户端电脑或浏览器内存中删除此cookie。
                            // maxAge 可以为正数，表示此cookie从创建到过期所能存在的时间，以秒为单位，
                            // 此cookie会存储到客户端电脑，以cookie文件形式保存，
                            // 不论关闭浏览器或关闭电脑，直到时间到才会过期
                            token1.maxAge(600L);//10分钟
                            token1.path("/"); //设置cookie的有效路径，否则不生效
                            token1.domain("www.test.com");//设置cookie的所属应用，否则不生效
                            response.addCookie(token1.build());
                        }
                    })
            );

        }else if(value.startsWith("/user/info")){// 请求前拦截
            MultiValueMap<String, HttpCookie> cookies = request.getCookies();
            log.info(JSONObject.toJSONString(cookies));
            List<HttpCookie> token = cookies.get("token");
            if (token == null || token.size() <= 0) {
                //无权限访问
                String errMsg = "会话失效";
                log.info(errMsg);
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.UNAUTHORIZED);//401
                DataBuffer wrap = response.bufferFactory().wrap(errMsg.getBytes("utf-8"));
                return response.writeWith(Mono.justOrEmpty(wrap));
            }
        }
        return chain.filter(exchange);
    }

}
